﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Input.Touch;
using G.XNA;


namespace YaoGuaiParty.Component
{
    /// <summary>
    /// 这是一个实现 IUpdateable 的游戏组件。
    /// </summary>
    public class GuaoWuParty : DrawableGameComponent
    {
        Game game;


        const int Size = 75;
        const int Thickness = 5;

        string[] strs = new string[] { "A", "B", "C", "D", "E" };
        Piece[][] btns;//用来存放屏幕上所有块的二维数组
        int rows;//行数
        int cols;//列数
        Rectangle canvasRect;//游戏块的范围
        Random random = new Random();

        public GuaoWuParty(Game game)
            : base(game)
        {
            // TODO: 在此处构造任何子组件
            this.game = game;
        }

        /// <summary>
        /// 允许游戏组件在开始运行之前执行其所需的任何初始化。
        /// 游戏组件能够在此时查询任何所需服务和加载内容。
        /// </summary>
        public override void Initialize()
        {
            // TODO: 在此处添加初始化代码


            base.Initialize();
            canvasRect = new Rectangle(100, 20, GraphicsDevice.Viewport.Width - 100 - 20, GraphicsDevice.Viewport.Height - 20 - 20);
            cols = canvasRect.Width / (Size + Thickness);//计算行数
            rows = canvasRect.Height / (Size + Thickness);//计算列数
            InitialArrary();
            Reset();
            Rectangle clientBounds = this.GraphicsDevice.Viewport.Bounds;
            SpriteFont segoe14 = this.game.Content.Load<SpriteFont>("Segoe14");
            int x = canvasRect.X;
            int y = canvasRect.Y;
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    btns[i][j].SpriteFont = segoe14;
                    btns[i][j].Destination = new Rectangle(x, y, Size, Size);
                    x += Size + Thickness;
                }
                x = canvasRect.X;
                y += Size + Thickness;
            }
        }
        protected override void LoadContent()
        {
            base.LoadContent();
        }
        //重置游戏区
        public void Reset()
        {
            CalcuResult result;
            do
            {
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        btns[i][j].Text = strs[random.Next(strs.Length)];
                    }
                }
                result = Calcu();
            } while (result.Orientation != CalcuResultOrientation.None);
        }
        //初始化二维数组
        private void InitialArrary()
        {
            if (btns != null)
            {
                //初始化之前先卸载原来的组件
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        Piece p = btns[i][j];
                        this.game.Components.Remove(p);
                    }
                }
            }
            btns = new Piece[rows][];
            for (int i = 0; i < rows; i++)
            {
                Piece[] temp = new Piece[cols];
                for (int j = 0; j < cols; j++)
                {
                    Piece btn = new Piece(this.game, null);
                    btn.Click += btn_Click;
                    this.game.Components.Add(btn);
                    temp[j] = btn;
                }
                btns[i] = temp;
            }
            //初始化各个块的信息
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    Piece p = btns[i][j];
                    p.Left = j == 0 ? null : btns[i][j - 1];
                    p.Top = i == 0 ? null : btns[i - 1][j];
                    p.Right = j == (cols - 1) ? null : btns[i][j + 1];
                    p.Bottom = i == (rows - 1) ? null : btns[i + 1][j];
                    p.Position = new Point(i, j);
                }
            }
        }
        Piece lastPressPiece;//上次按下的按钮
        void btn_Click(object sender, EventArgs e)
        {
            Piece piece = sender as Piece;
            if (lastPressPiece == null)
            {
                lastPressPiece = piece;
            }
            else if (lastPressPiece != piece)
            {
                //判断两次按下的按钮是否是相邻的按钮
                if (lastPressPiece.Left == piece || lastPressPiece.Top == piece || lastPressPiece.Right == piece || lastPressPiece.Bottom == piece)
                {
                    ExchangePieceText(lastPressPiece, piece);//交换文本位置
                    var result = Calcu();//计算本次的结果
                    switch (result.Orientation)
                    {
                        case CalcuResultOrientation.None:
                            ExchangePieceText(lastPressPiece, piece);//如果没有发生消除，那么还原两个文本的位置
                            break;
                        case CalcuResultOrientation.Horizontal:
                            DoHorizontal(result);
                            break;
                        case CalcuResultOrientation.Vertical:
                            DoVertical(result);
                            break;
                    }
                }
                lastPressPiece = null;
            }
        }
        //垂直方向的消除
        private void DoVertical(CalcuResult result)
        {
            int count = result.Count;
            Piece temp = result.Start;
            ClearCount++;
            //calcuBtn.Text = clearCount.ToString();
            while (count > 0)
            {
                //temp.Text = strs[random.Next(strs.Length)];
                if (temp != null)
                {
                    Piece t = temp;
                    t.Text = strs[random.Next(strs.Length)];
                    while (true)
                    {
                        if (t.Top == null)
                        {
                            break;
                        }
                        else
                        {
                            ExchangePieceText(t, t.Top);
                            t = t.Top;
                        }
                    }
                }
                temp = temp.Bottom;
                count--;
            }
            var r = Calcu();
            switch (r.Orientation)
            {
                case CalcuResultOrientation.Horizontal:
                    DoHorizontal(r);
                    break;
                case CalcuResultOrientation.Vertical:
                    DoVertical(r);
                    break;
            }
        }

        //水平方向的消除
        private void DoHorizontal(CalcuResult result)
        {
            int count = result.Count;
            Piece temp = result.Start;
            ClearCount++;
            //calcuBtn.Text = clearCount.ToString();
            while (count > 0)
            {
                //temp.Text = strs[random.Next(strs.Length)];
                
                if (temp != null)
                {
                    Piece t = temp;
                    t.Text = strs[random.Next(strs.Length)];
                    while (true)
                    {
                        if (t.Top == null)
                        {
                            break;
                        }
                        else
                        {
                            ExchangePieceText(t, t.Top);
                            t = t.Top;
                        }
                    }
                }
                temp = temp.Right;
                count--;
            }
            var r = Calcu();
            switch (r.Orientation)
            {
                case CalcuResultOrientation.Horizontal:
                    DoHorizontal(r);
                    break;
                case CalcuResultOrientation.Vertical:
                    DoVertical(r);
                    break;
            }
        }
        /// <summary>
        /// 交换两个piece的文本
        /// </summary>
        private void ExchangePieceText(Piece p1, Piece p2)
        {
            string temp = p1.Text;
            p1.Text = p2.Text;
            p2.Text = temp;
        }
        public event EventHandler ClearCountChange;
        private int clearCount;
        public int ClearCount
        {
            get
            {
                return clearCount;
            }
            set
            {
                clearCount = value;
                if (ClearCountChange != null)
                    ClearCountChange(this, EventArgs.Empty);
            }
        }

        private CalcuResult Calcu()
        {
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    Piece p = btns[i][j];
                    //计算水平方向
                    Piece temp = p;
                    int count = 1;
                    while (temp != null && temp.Right != null && temp.Right.Text == p.Text)
                    {
                        count++;
                        temp = temp.Right;
                    }
                    if (count >= 3)
                    {
                        return new CalcuResult(p, temp, count, CalcuResultOrientation.Horizontal);
                    }
                    //计算垂直方向
                    count = 1;
                    temp = p;
                    while (temp != null && temp.Bottom != null && temp.Bottom.Text == p.Text)
                    {
                        count++;
                        temp = temp.Bottom;
                    }
                    if (count >= 3)
                    {
                        return new CalcuResult(p, temp, count, CalcuResultOrientation.Vertical);
                    }
                }
            }
            return new CalcuResult() { Orientation = CalcuResultOrientation.None };
        }

        /// <summary>
        /// 允许游戏组件进行自我更新。
        /// </summary>
        /// <param name="gameTime">提供计时值的快照。</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: 在此处添加更新代码
            TouchCollection touches = TouchPanel.GetState();

            foreach (TouchLocation touch in touches)
            {
                bool touchHandled = false;

                foreach (GameComponent component in this.game.Components)
                    if (component is IProcessTouch &&
                        (component as IProcessTouch).ProcessTouch(touch))
                    {
                        touchHandled = true;
                        break;
                    }

                if (touchHandled)
                    continue;
            }
            base.Update(gameTime);
        }
    }
}
